package com.john.test.http.proxy.validator;

import com.john.test.http.proxy.data.ProxyItem;
import com.john.http.core.util.HtmlFetchUtil;
import com.john.test.http.proxy.validator.data.TestSite;
import com.john.test.http.proxy.validator.data.ValidatorConfig;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.fluent.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

/**
 * 〈一句话功能简述〉<br/>
 * 〈功能详细描述〉
 *
 * @author jiangguangtao on 2016/4/28.

 */
public class ProxyTesterRunner implements Runnable {
    private static final Logger log = LoggerFactory.getLogger(ProxyTesterRunner.class);
    private ValidatorConfig validatorConfig;


    /**
     * 代理测试类
     *
     * @param validatorConfig
     */
    public ProxyTesterRunner(ValidatorConfig validatorConfig) {
        this.validatorConfig = validatorConfig;
    }


    @Override
    public void run() {
        ProxyItem proxyItem = validatorConfig.getProxyItem();
        List<TestSite> testSites = validatorConfig.getTestSites();

        log.info("测试代理:{}, 测试网站：{}", proxyItem.simpleDesc(), validatorConfig.getTestSites());
        List<BigDecimal> delaySums = initDelaySums(testSites.size());
        HttpHost proxyHost = new HttpHost(proxyItem.getIp(), proxyItem.getPort(), proxyItem.getProxyType());
        int idx = 0;
        Double minDelay = null;
        Double maxDelay = validatorConfig.getOneTimeMaxDelay() * validatorConfig.getTestSites().size();
        for (; idx < testSites.size(); idx++) {
            TestSite site = testSites.get(idx);
            log.debug("测试代理:{} 连接网店：{}", proxyItem.simpleDesc(), site);
            BigDecimal delaySum = delaySums.get(idx);
            for (int i = 0; i < 3; i++) {

                double oneDelay = proxy(site, validatorConfig.getConnectTimeout(), proxyHost, maxDelay);
                delaySum = delaySum.add(BigDecimal.valueOf(oneDelay));
            }
            Double delay = delaySum.divide(BigDecimal.valueOf(3)).setScale(2, RoundingMode.HALF_UP).doubleValue();
            if (null == minDelay) {
                minDelay = delay;
            } else {
                if (minDelay > delay) {
                    minDelay = delay;
                }
            }
        }
//        double delay = delaySum.divide(BigDecimal.valueOf(3 * testSites.size())).setScale(2, RoundingMode.HALF_UP).doubleValue();
        proxyItem.setLocalDelay(minDelay);
        validatorConfig.getResultQueue().add(proxyItem);
    }


    private List<BigDecimal> initDelaySums(int size) {
        List<BigDecimal> delaySums = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            delaySums.add(i, new BigDecimal(0));
        }
        return delaySums;
    }

    private double proxy(TestSite testSite, int timeout, HttpHost proxyHost, Double maxDelay) {
        try {
            long begin = System.currentTimeMillis();
            HttpResponse httpResponse = Request.Get(testSite.getUrl())
                    .userAgent(HtmlFetchUtil.USER_AGENT)
                    .connectTimeout(timeout)
                    .viaProxy(proxyHost)
                    .execute().returnResponse();
            StatusLine statusLine = httpResponse.getStatusLine();
            double delay = getDelayTime(begin);
            log.debug("proxy:{} delay:{} and return status:{}", proxyHost, delay, statusLine);
            return delay;
        } catch (IOException e) {
//            log.debug("测试超时 代理：{}, 测试站点：{}", proxyHost, testSite);
            return maxDelay;
        }
    }

    private double getDelayTime(long begin) {
        long times = System.currentTimeMillis() - begin;
        return times / 1000.0;
    }
}
